package com.linkhub.oms.data.sync.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.linkhub.oms.common.util.QtOptionalUtil;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.dao.mpservice.IShopProductService;
import com.linkhub.oms.dao.mpservice.IShopProductSkuService;
import com.linkhub.oms.data.sync.api.shopify.domain.response.ShopProductResponse;
import com.linkhub.oms.data.sync.api.shopify.enums.ProductStatusEnum;
import com.linkhub.oms.data.sync.service.ProductSyncBizService;
import com.linkhub.oms.entity.ShopProductEntity;
import com.linkhub.oms.entity.ShopProductSkuEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * @Description: ProductSyncBizService
 * @Author: echo
 * @Date: 2024/3/23 12:50
 * @Version: 1.0
 */
@Slf4j
@Service
public class ProductSyncBizServiceImpl implements ProductSyncBizService {
    @Resource
    private IShopProductService shopProductService;
    @Resource
    private IShopProductSkuService shopProductSkuService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sync(String sysShopId, ShopProductResponse response) {
        List<ShopProductResponse.Products> products = response.getProducts();
        Map<Boolean, List<ShopProductResponse.Products>> activeProductMap = QtStreamUtil.partition(products,
                product -> ProductStatusEnum.ACTIVE.getStatus().equals(product.getStatus()));

        delete(sysShopId, activeProductMap.get(false));

        List<ShopProductResponse.Products> saveOrUpdateList = activeProductMap.get(true);
        if (CollUtil.isEmpty(saveOrUpdateList)) {
            return;
        }

        List<ShopProductEntity> productList = shopProductService.listShopProducts(sysShopId, getProductIds(saveOrUpdateList));
        List<Long> presentProductIds = QtStreamUtil.map(productList, ShopProductEntity::getProductId);
        Map<Boolean, List<ShopProductResponse.Products>> saveOrUpdateMap = QtStreamUtil.partition(saveOrUpdateList,
                product -> presentProductIds.contains(product.getId()));

        update(sysShopId, saveOrUpdateMap.get(true));

        save(sysShopId, saveOrUpdateMap.get(false));
    }

    private void delete(String sysShopId, List<ShopProductResponse.Products> products) {
        if (CollUtil.isEmpty(products)) {
            log.info("delete products isEmpty <<<<<<");
            return;
        }
        List<Long> productIds = getProductIds(products);
        // 删除主表
        shopProductService.deleteShopProducts(sysShopId, productIds);
        // 删除子表
        shopProductSkuService.deleteShopProductSkus(sysShopId, productIds);
    }

    private void save(String sysShopId, List<ShopProductResponse.Products> products) {
        if (CollUtil.isEmpty(products)) {
            log.info("save products isEmpty <<<<<<");
            return;
        }
        List<ShopProductEntity> productList = QtStreamUtil.map(products,
                product -> convertProduct(sysShopId, product));
        List<ShopProductSkuEntity> skuList = QtStreamUtil.flatMap(products,
                product -> convertProductSkus(sysShopId, product).stream());
        shopProductService.saveBatch(productList);
        shopProductSkuService.saveBatch(skuList);

    }

    private void update(String sysShopId, List<ShopProductResponse.Products> products) {
        if (CollUtil.isEmpty(products)) {
            log.info("update products isEmpty <<<<<<");
            return;
        }
        // 先删后插
        delete(sysShopId, products);
        save(sysShopId, products);


    }

    private List<Long> getProductIds(List<ShopProductResponse.Products> products) {
        return QtStreamUtil.map(products, ShopProductResponse.Products::getId);
    }

    private ShopProductEntity convertProduct(String sysShopId, ShopProductResponse.Products product) {
        ShopProductEntity entity = new ShopProductEntity();
        entity.setSysShopId(sysShopId);
        entity.setProductId(product.getId());
        entity.setTitle(product.getTitle());
        entity.setCreatedAt(product.getCreatedAt());
        entity.setUpdatedAt(product.getUpdatedAt());
        entity.setCreatedTime(LocalDateTime.now());
        entity.setUpdateTime(LocalDateTime.now());

        return entity;

    }

    private List<ShopProductSkuEntity> convertProductSkus(String sysShopId, ShopProductResponse.Products product) {
        List<ShopProductResponse.Products.Variants> variants = product.getVariants();
        List<ShopProductSkuEntity> result = Lists.newArrayListWithCapacity(variants.size());
        Map<Long, ShopProductResponse.Products.Images> imagesMap = QtStreamUtil.toMap(product.getImages(),
                ShopProductResponse.Products.Images::getId);
        for (ShopProductResponse.Products.Variants variant : variants) {
            ShopProductSkuEntity entity = new ShopProductSkuEntity();
            entity.setSysShopId(sysShopId);
            entity.setProductId(variant.getProductId());
            entity.setSkuId(variant.getId());
            entity.setTitle(variant.getTitle());
            entity.setSku(variant.getSku());

            String imageUrl = QtOptionalUtil.of(variant.getImageId())
                    .map(imagesMap::get)
                    .map(ShopProductResponse.Products.Images::getSrc)
                    .orElseGet(() ->
                            QtOptionalUtil.of(product.getImage())
                                    .map(ShopProductResponse.Products.Image::getSrc)
                                    .orElse(null));

            entity.setImgUrl(imageUrl);

            entity.setCreatedAt(variant.getCreatedAt());
            entity.setUpdatedAt(variant.getUpdatedAt());
            entity.setCreatedTime(LocalDateTime.now());
            entity.setUpdateTime(LocalDateTime.now());
            result.add(entity);

        }

        return result;

    }
}
